package cn.xnatural.app;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 属性操作接口
 */
public interface IAttr {
    Object getAttr(String key);

    /**
     * 修改配置
     * @return 修改了多少条记录
     */
    int setAttr(String key, Object value);


    default <T> T getAttr(String key, Class<T> type) {
        return Utils.to(getAttr(key), type);
    }
    default <T> T getAttr(String key, Class<T> type, T defaultValue) {
        return getAttr(key, type, (Supplier<T>) () -> defaultValue);
    }
    default <T> T getAttr(String key, Class<T> type, Supplier<T> defaultValueGetter) {
        T v = getAttr(key, type);
        return v == null ? defaultValueGetter.get() : v;
    }


    default String getStr(String name) {
        return getAttr(name, String.class);
    }
    default String getStr(String name, String defaultValue) {
        return getAttr(name, String.class, defaultValue);
    }
    default String getStr(String name, Supplier<String> defaultValueGetter) {
        return getAttr(name, String.class, defaultValueGetter);
    }
    default List<String> getStrs(String name) {
        String v = getStr(name);
        if (v == null || v.isEmpty()) return null;
        return Arrays.stream(v.split(",")).filter(Objects::nonNull).map(String::trim).filter(s -> !s.isEmpty())
                .collect(Collectors.toList());
    }


    default Boolean getBoolean(String name) {
        return getAttr(name, Boolean.class);
    }
    default Boolean getBoolean(String name, Boolean defaultValue) {
        return getAttr(name, Boolean.class, defaultValue);
    }
    default Boolean getBoolean(String name, Supplier<Boolean> defaultValueGetter) {
        return getAttr(name, Boolean.class, defaultValueGetter);
    }
    default List<Boolean> getBooleans(String name) {
        String v = getStr(name);
        if (v == null || v.isEmpty()) return null;
        return Arrays.stream(v.split(",")).filter(Objects::nonNull).map(String::trim).filter(s -> !s.isEmpty())
                .map(s -> Utils.to(s, Boolean.class))
                .collect(Collectors.toList());
    }

    default Integer getInteger(String name) {
        return getAttr(name, Integer.class);
    }
    default Integer getInteger(String name, Integer defaultValue) {
        return getAttr(name, Integer.class, defaultValue);
    }
    default Integer getInteger(String name, Supplier<Integer> defaultValueGetter) {
        return getAttr(name, Integer.class, defaultValueGetter);
    }
    default List<Integer> getIntegers(String name) {
        String v = getStr(name);
        if (v == null || v.isEmpty()) return null;
        return Arrays.stream(v.split(",")).filter(Objects::nonNull).map(String::trim).filter(s -> !s.isEmpty())
                .map(s -> Utils.to(s, Integer.class))
                .collect(Collectors.toList());
    }

    default Long getLong(String name) {
        return getAttr(name, Long.class);
    }
    default Long getLong(String name, Long defaultValue) {
        return getAttr(name, Long.class, defaultValue);
    }
    default Long getLong(String name, Supplier<Long> defaultValueGetter) {
        return getAttr(name, Long.class, defaultValueGetter);
    }
    default List<Long> getLongs(String name) {
        String v = getStr(name);
        if (v == null || v.isEmpty()) return null;
        return Arrays.stream(v.split(",")).filter(Objects::nonNull).map(String::trim).filter(s -> !s.isEmpty())
                .map(s -> Utils.to(s, Long.class))
                .collect(Collectors.toList());
    }


    default Double getDouble(String name) {
        return getAttr(name, Double.class);
    }
    default Double getDouble(String name, Double defaultValue) {
        return getAttr(name, Double.class, defaultValue);
    }
    default Double getDouble(String name, Supplier<Double> defaultValueGetter) {
        return getAttr(name, Double.class, defaultValueGetter);
    }
    default List<Double> getDoubles(String name) {
        String v = getStr(name);
        if (v == null || v.isEmpty()) return null;
        return Arrays.stream(v.split(",")).filter(Objects::nonNull).map(String::trim).filter(s -> !s.isEmpty())
                .map(s -> Utils.to(s, Double.class))
                .collect(Collectors.toList());
    }


    default BigDecimal getBigDecimal(String name) {
        return getAttr(name, BigDecimal.class);
    }
    default BigDecimal getBigDecimal(String name, BigDecimal defaultValue) {
        return getAttr(name, BigDecimal.class, defaultValue);
    }
    default BigDecimal getBigDecimal(String name, Supplier<BigDecimal> defaultValueGetter) {
        return getAttr(name, BigDecimal.class, defaultValueGetter);
    }
    default List<BigDecimal> getBigDecimals(String name) {
        String v = getStr(name);
        if (v == null || v.isEmpty()) return null;
        return Arrays.stream(v.split(",")).filter(Objects::nonNull).map(String::trim).filter(s -> !s.isEmpty())
                .map(s -> Utils.to(s, BigDecimal.class))
                .collect(Collectors.toList());
    }

    default Duration getDuration(String name) {
        return getAttr(name, Duration.class);
    }
    default Duration getDuration(String name, Duration defaultValue) {
        return getAttr(name, Duration.class, defaultValue);
    }
    default Duration getDuration(String name, Supplier<Duration> defaultValueGetter) {
        return getAttr(name, Duration.class, defaultValueGetter);
    }
    default List<Duration> getDurations(String name) {
        String v = getStr(name);
        if (v == null || v.isEmpty()) return null;
        return Arrays.stream(v.split(",")).filter(Objects::nonNull).map(String::trim).filter(s -> !s.isEmpty())
                .map(s -> Utils.to(s, Duration.class))
                .collect(Collectors.toList());
    }
}
